<template>
	<div class='project-basic-info'>
		<el-form
			ref="formRef"
			:model="infoForm"
			:rules="typeMap ? typeMap.formRule : {}"
			label-width="80px"
			class="demo-ruleForm"
		>
			<el-form-item
				label="项目头像"
				prop="avatarUrl"
			>
				<ChooseImgs
					:files="infoForm.avatarUrl ? [{url: infoForm.avatarUrl,name:'avatar'}] : []"
					@changeFiles="uploadImg($event,'avatarUrl')"
				/>
			</el-form-item>
			<el-form-item
				label="项目名"
				prop="name"
			>
				<el-input
					style="width: 400px;"
					clearable
					placeholder="请输入项目名"
					v-model="infoForm.name"
				/>
			</el-form-item>
			<el-form-item
				label="项目标签"
				prop="tags"
			>
				<TagsInput
					:tags="infoForm.tags"
					:splitKey="' '"
					@changeTag="infoForm.tags=$event"
				/>
			</el-form-item>
			<div v-if="props.projectType === 'competition'">
				<el-form-item
					label="参与比赛"
					prop="compId"
				>
					<el-select
						style="width: 400px;"
						clearable
						filterable
						allow-create
						placeholder="请输入参与的比赛名"
						default-first-option
						v-model="infoForm.compId"
						@change="selectComp"
					>
						<el-option
							v-for="item in competitions"
							:key="item.id"
							:label="item.name"
							:value="item.id"
						/>
					</el-select>
				</el-form-item>
				<el-form-item
					label="获奖等级"
					prop="awardLevel"
				>
					<el-select
						style="width: 200px;"
						placeholder="请输入获奖等级"
						:disabled="!infoForm.compId"
						v-model="infoForm.awardLevel"
					>
						<el-option
							v-for="item in awardLevels"
							:key="item.value"
							:label="item.label"
							:value="item.value"
						/>
					</el-select>
				</el-form-item>
				<el-form-item
					label="获奖时间"
					prop="awardTime"
				>
					<el-date-picker
						style="width: 200px;"
						type="date"
						placeholder="选择获奖时间"
						v-model="infoForm.awardTime"
					/>
				</el-form-item>
				<el-form-item
					label="获奖证明"
					prop="awardProveUrl"
				>
					<ChooseImgs
						:files="infoForm.awardProveUrl ? [{url: infoForm.awardProveUrl,name:'awardProve'}] : []"
						@changeFiles="uploadImg($event,'awardProveUrl')"
					/>
				</el-form-item>
			</div>
			<div  v-if="props.projectType === 'courseDesign'">
				<el-form-item
					label="课程类型"
					prop="courseType"
				>
					<el-select
						style="width: 200px;"
						placeholder="请选择课程类型"
						@change="loadCourses"
						v-model="infoForm.courseType"
					>
						<el-option
							v-for="item in courseTypes"
							:key="item.value"
							:label="item.label"
							:value="item.value"
						/>
					</el-select>
				</el-form-item>
				<el-form-item
					label="课程名"
					prop="courseId"
				>
					<el-select
						style="width: 400px;"
						clearable
						filterable
						allow-create
						placeholder="请输入具体课程名"
						default-first-option
						:disabled="courses.length===0"
						v-model="infoForm.courseId"
						@change="selectCourseName"
					>
						<el-option
							v-for="item in courses"
							:key="item.courseId"
							:label="item.courseName"
							:value="item.courseId"
						/>
					</el-select>
				</el-form-item>
			</div>

			<el-form-item
				label="项目介绍"
				prop="intro"
			>
				<el-input
					style="width: 500px;"
					type="textarea"
					maxlength="-1"
					rows="4"
					placeholder="请输入项目介绍"
					v-model="infoForm.intro"
				/>
			</el-form-item>
		</el-form>
	</div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { computed } from '@vue/reactivity'
import type { FormInstance } from 'element-plus'
import moment from 'moment'
import { getPublicUploadSign } from '@/api/system'
import { postCourse } from '@/api/course'
import { postCompProject, postCourseDesign, postMember, putCompProject, putCourseDesign } from '@/api/project'
import { RULE_COMP_PROJECT_BASIC_INFO, RULE_COURSE_DESIGN_BASIC_INFO } from '@/constants/rules'
import { LOGO } from '@/constants/index'
import { PRIZE_LEVELS, COMP_TYPES } from '@/constants/project'
import { $loading, $hideLoading, $error, $pushTo, $success } from '@/utils/functions'
import { storeGetter } from '@/utils/store'
import { cosUpload } from '@/utils/file'
import { getCompetitions, getCoursesData } from '@/utils/buffer'
import type { CompetitionType } from '@/modules/competition'
import type { CourseType } from '@/modules/course'
import type { ProjectBasicInfoType, ProjectType, CompProjectType } from '@/modules/project'
import TagsInput from '@/components/TagsInput/index.vue'
import ChooseImgs from '@/components/ChooseImg/index.vue'

const props = defineProps<{
	projectType: ProjectType,
	project?: CompProjectType
}>()

const formRef = ref<FormInstance>()
const infoForm = reactive<ProjectBasicInfoType>({
  name: '', // 项目名称
  avatarUrl: '', // 团队头像
  tags: '', // 标签
  intro: '', // 描述

  compId: null, // 比赛id
  compName: '', // 比赛名称
  awardLevel: null, // 获奖等级
  awardTime: '', // 获奖时间
  awardProveUrl: '', // 获奖证明

  courseType: null, // 课程类型
  courseId: null, // 课程id
  courseName: '', // 课程名
})

/**
 * 图片发生改变，触发上传
 * @param files 文件列表
 * @param key 修改的关键字段
 */
const uploadImg = async(files:any, key:string) => {
  /* 文件长度为0，说明是删除文件 */
  if (files.length === 0) {
    infoForm[ key ] = ''
    return
  }
  $loading()
  try {
    const sign = await getPublicUploadSign(`${ key }-${ Date.now() }.JPG`)
    const res = await cosUpload(files[ 0 ], sign.data)
    infoForm[ key ] = res
  } catch (err) {
    console.log(err)
  }
  $hideLoading()
}

const competitions = ref<CompetitionType[]>([])
const courseTypes = ref(COMP_TYPES)

if (props.projectType === 'competition') {
/* 比赛筛选列表 */
  getCompetitions()
    .then(res => { competitions.value = res })
}

/**
 * 选择比赛
 */
const selectComp = () => {
  infoForm.awardLevel = null
  const comp = competitions.value.find(item => item.id === infoForm.compId)
  infoForm.compName = comp ? comp.name : ''
}
/* 根据比赛id筛选对应的获奖等级 */
const awardLevels = computed(() => {
  const match = competitions.value.find(item => item.id === infoForm.compId)

  if (match) {
    const start = (5 - match.level) * 3

    return PRIZE_LEVELS.slice(start, start + 3)
  }
  return PRIZE_LEVELS
})

const courses = ref<CourseType[]>([])
/**
 * 选择课程类型，通过接口请求对应类型的课程
 */
const loadCourses = async() => {
  if (!infoForm.courseType) {
    return
  }
  courses.value = (await getCoursesData(infoForm.courseType)).data
  infoForm.courseId = null
}
/**
 * 选择课程名
 */
const selectCourseName = () => {
  const course = courses.value.find(item => item.courseId === infoForm.courseId)
  if (course) {
    infoForm.courseName = course.courseName
  }
}

/**
 * 校验并获取页面的数据返回
 */
const getPageData = async() => {
  let data:ProjectBasicInfoType | null = null

  if (props.projectType === 'competition') { // 比赛项目数据
    /* 计算compId */
    data = {
      name: infoForm.name,
      avatarUrl: infoForm.avatarUrl || LOGO,
      compId: typeof infoForm.compId === 'string' ? 0 : infoForm.compId,
      tags: infoForm.tags,
      compName: infoForm.compName,
      awardLevel: infoForm.awardLevel,
      awardTime: moment(infoForm.awardTime).format('YYYY-MM'),
      awardProveUrl: infoForm.awardProveUrl,
      intro: infoForm.intro,
    }
  } else if (props.projectType === 'courseDesign') { // 课设项目数据
    let courseId = infoForm.courseId
    if (typeof courseId === 'string' && infoForm.courseId && infoForm.courseType) { // 填写的课程不存在数组中，说明是新课程
      try {
        courseId = (await postCourse(String(infoForm.courseId), infoForm.courseType)).data
      } catch (err) {
        return Promise.reject(err)
      }
    }
    /* 构造数据 */
    data = {
      courseId,
      name: infoForm.name,
      avatarUrl: infoForm.avatarUrl,
      tags: infoForm.tags,
      intro: infoForm.intro,
    }
  }
  return data
}

/**
 * 点击创建项目
 */
const createProject = async(formEl:FormInstance) => {
  formEl.validate(async(valid) => {
    if (!valid) return
    const data = await getPageData()

    if (data) {
      $loading()
      try {
        const projectId = await typeMap?.createFn(data)
        $success('创建成功')
        $pushTo('ProjectEdit', {}, { id: projectId })
      } catch (err) {
        $error('创建项目失败')
      }
      $hideLoading()
    }
  })
}

/**
 * 创建竞赛项目
 */
const createCompProject = async(data:ProjectBasicInfoType) => {
  let projectId:number = 0
  return postCompProject(data)
    .then(({ data }:{data:number}) => {
      projectId = data
      return postMember({
        projectId,
        member: {
          memberUserId: storeGetter('getUserInfo').userInfo.userId,
          rank: 1,
          job: '负责人',
          editable: true
        }
      })
    })
    .then(() => projectId)
}

/**
 * 创建课设项目
 */
const createCourseProject = async(data:ProjectBasicInfoType) => postCourseDesign(data).then((res:any) => res.data)

/**
 * 点击更新项目
 */
const updateProject = async(formEl:FormInstance) => {
  formEl.validate(async(valid) => {
    if (!valid) return
    const data = await getPageData()

    if (data) {
      $loading()
      try {
        props.project && 	await typeMap.updateFn(props.project.id, data)
        $success('更新成功')
      } catch (err) {
        $error('更新项目失败')
      }
      $hideLoading()
    }
  })
}

/* 如果有project属性，说明是更新项目, 初始化数据 */
if (props.project) {
  for (const key in infoForm) {
    infoForm[ key ] = props.project[ key ]
  }
}

const typeMap = {
  competition: {
    formRule: RULE_COMP_PROJECT_BASIC_INFO,
    createFn: createCompProject,
    updateFn: putCompProject
  },
  courseDesign: {
    formRule: RULE_COURSE_DESIGN_BASIC_INFO,
    createFn: createCourseProject,
    updateFn: putCourseDesign
  }
}[ props.projectType ]
defineExpose({
  formRef,
  createProject,
  updateProject
})
</script>

<style lang="scss" scoped>
.project-basic-info {
  .el-form-item {
    margin-bottom: 30px;
  }
}
</style>
